package top.itbook.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;

/**
 * SHA-224单向散列函数，其相比于MD2、MD5、SHA-1已经有了相对的提升
 * 至少目前截止到2022-7-11为止，还没有任何关于证明SHA-224发生不同内容产生哈希碰撞的消息。
 */
public class SHA224 extends Provider {
    private static SHA224 instance; // 本类对象
    final private static String salt = "@KingSHA224.top"; // 盐值

    // 私有化构造器
    private SHA224(String name,String versionStr,String info){
        super(name,versionStr,info);
    }

    /**
     * 获取本类实例化对象
     * 懒汉单例设计模式
     * @return SHA-224 哈希加密算法对象
     */
    public static SHA224 getInstance(){
        if (instance == null){
            instance = new SHA224("King","0.2","SHA-224信息摘要加密算法，因为加了盐的特性，这让不知道盐值的人很难通过彩虹表破解出原文内容。");
        }
        return instance;
    }

    /**
     * SHA - 224 信息摘要算法 - 不可逆加密 - 加密字符串
     * @param content 要获取摘要的字符串
     * @return 若成功获取摘要则返回十六进制字符串，若发生不可预见的错误则返回null
     */
    @Deprecated
    public String SHA224encryption(String content){
        MessageDigest messageDigest;
        String s = null; // 加密后的字符串
        try {
            messageDigest = MessageDigest.getInstance("SHA-224"); // 获取实例化 对象
            // 更新摘要
            messageDigest.update(content.getBytes());
            // 将要加密的字符串转换成哈希值
            byte[] resultBytes = messageDigest.digest();
            // 将信息转换为十六进制字符串
            s = convertString(resultBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return s;
    }

    /**
     * SHA224加密算法(加盐) - 不可逆加密 - 加密字符串
     * @param content 要加密的字符串
     * @return MD2算法加密后的密文 - 若返回null则可能出现无法预知的报错
     */
    public String SHA224encryptionPLUS(String content){
        MessageDigest messageDigest;
        String s = null; // 加密后的字符串
        try {
            messageDigest = MessageDigest.getInstance("SHA-224");
            // 原字符串与盐值拼接
            content = content + salt;
            // 更新摘要
            messageDigest.update(content.getBytes());
            // 将要加密的字符串转换成哈希值
            byte[] resultBytes = messageDigest.digest();
            // 将信息转换为十六进制字符串
            s = convertString(resultBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return s;
    }

    // 将字节数组转换为十六进制字符串
    private String convertString(byte[] bytes){
        StringBuilder stringBuilder = new StringBuilder(bytes.length * 2);
        for (byte aByte : bytes) {
            stringBuilder.append(String.format("%02x",aByte & 0xff));
        }
        return stringBuilder.toString();
    }
}